package com.tapadoo.alerter;


import ohos.aafwk.ability.AbilitySlice;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.media.image.PixelMap;
import ohos.utils.net.Uri;

import java.lang.ref.WeakReference;

/**
 * Alert helper class. Will attach a temporary layout to the current activity's content, on top of
 * all other views. It should appear under the status bar.
 *
 * @author Kevin Murphy
 * @since 03/11/2015.
 */
public final class Alerter {

    private static WeakReference<AbilitySlice> activityWeakReference;
    private static WeakReference<Component> componentWeakReference;

    private Alert alert;

    /**
     * Constructor
     */
    private Alerter() {
        //Utility classes should not be instantiated
    }

    public static Alerter create(final AbilitySlice activity, ComponentContainer componentContainer) {
        if (activity == null) {
            throw new IllegalArgumentException("Activity cannot be null!");
        }

        final Alerter alerter = new Alerter();

        //Hide current Alert, if one is active
        alerter.setActivity(activity, componentContainer);
        alerter.setAlert(new Alert(activity, componentContainer));
        return alerter;
    }

    public static Alerter create(final AbilitySlice activity, ComponentContainer componentContainer, int layoutId) {
        if (activity == null) {
            throw new IllegalArgumentException("Activity cannot be null!");
        }

        final Alerter alerter = new Alerter();

        //Hide current Alert, if one is active
        alerter.setActivity(activity, componentContainer);
        alerter.setAlert(new Alert(activity, componentContainer, layoutId));
        return alerter;
    }


    /**
     * Check if an Alert is currently showing
     *
     * @return True if an Alert is showing, false otherwise
     */
    public static boolean isShowing() {
        boolean isShowing = false;
        if (componentWeakReference != null && componentWeakReference.get() != null) {
            isShowing = componentWeakReference.get().findComponentById(ResourceTable.Id_flAlertBackground) != null;
        }

        return isShowing;
    }

    /**
     * Shows the Alert, after it's built
     *
     * @return An Alert object check can be altered or hidden
     */
    public Alert show() {
        //This will get the Activity Window's DecorView
        if (getComponentWeakReference() != null) {
            final ComponentContainer decorView = (ComponentContainer) getComponentWeakReference().get();
        }
        return getAlert();
    }


    /**
     * Set Title of the Alert
     *
     * @param title Title as a String
     * @return This Alerter
     */
    public Alerter setTitle(final String title) {
        if (getAlert() != null) {
            getAlert().setTitle(title);
        }

        return this;
    }

    /**
     * Set Gravity of the Alert
     *
     * @param gravity Gravity of Alert
     * @return This Alerter
     */
    public Alerter setContentGravity(final int gravity) {
        if (getAlert() != null) {
            getAlert().setContentGravity(gravity);
        }

        return this;
    }


    /**
     * Sets the Alert Text
     *
     * @param text String of Alert Text
     * @return This Alerter
     */
    public Alerter setText(final String text) {
        if (getAlert() != null) {
            getAlert().setText(text);
        }

        return this;
    }

    /**
     * Set the Alert's Background Colour
     *
     * @param colorInt Colour int value
     * @return This Alerter
     */
    public Alerter setBackgroundColorInt(final int colorInt) {
        if (getAlert() != null) {
            getAlert().setAlertBackgroundColor(colorInt);
        }

        return this;
    }


    /**
     * Set the Alert's Icon
     *
     * @param iconId The Drawable's Resource Idw
     * @return This Alerter
     */
    public Alerter setIcon(final int iconId) {
        if (getAlert() != null) {
            getAlert().setIcon(iconId);
        }
        return this;
    }

    /**
     * Set the Alert's Icon
     *
     * @param bitmap The Bitmap object to use for the icon.
     * @return This Alerter
     */
    public Alerter setIcon(final PixelMap bitmap) {
        if (getAlert() != null) {
            getAlert().setIcon(bitmap);
        }

        return this;
    }

    /**
     * Set the Alert's Icon
     *
     * @param drawable The Drawable to use for the icon.
     * @return This Alerter
     */
    public Alerter setIcon(final Element drawable) {
        if (getAlert() != null) {
            getAlert().setIcon(drawable);
        }

        return this;
    }

    public Alerter setIconSize(final int size) {
        if (getAlert() != null) {
            getAlert().setIconSize(size);
        }
        return this;
    }


    public Alerter addButton(String text, int textColor, int backgroundColor, int width, int height, Component.ClickedListener clickedListener) {
        getAlert().addButton(text, textColor, backgroundColor, width, height, clickedListener);
        return this;
    }


    /**
     * Hide the Icon
     *
     * @return This Alerter
     */
    public Alerter hideIcon() {
        if (getAlert() != null) {
            getAlert().getIcon().setVisibility(Component.HIDE);
        }

        return this;
    }

    /**
     * Set the onClickListener for the Alert
     *
     * @param onClickListener The onClickListener for the Alert
     * @return This Alerter
     */
    public Alerter setOnClickListener(final Component.ClickedListener onClickListener) {
        if (getAlert() != null) {
            getAlert().setOnClickListener(onClickListener);

        }

        return this;
    }

    /**
     * Set the on screen duration of the alert
     *
     * @param milliseconds The duration in milliseconds
     * @return This Alerter
     */
    public Alerter setDuration(final long milliseconds) {
        if (getAlert() != null) {
            getAlert().setDuration(milliseconds);
        }
        return this;
    }

    /**
     * Enable or Disable Icon Pulse Animations
     *
     * @param pulse True if the icon should pulse
     * @return This Alerter
     */
    public Alerter enableIconPulse(final boolean pulse) {
        if (getAlert() != null) {
            getAlert().pulseIcon(pulse);
        }
        return this;
    }

    /**
     * Set whether to show the icon in the alert or not
     *
     * @param showIcon True to show the icon, false otherwise
     * @return This Alerter
     */
    public Alerter showIcon(final boolean showIcon) {
        if (getAlert() != null) {
            getAlert().showIcon(showIcon);
        }
        return this;
    }

    /**
     * Enable or disable infinite duration of the alert
     *
     * @param infiniteDuration True if the duration of the alert is infinite
     * @return This Alerter
     */
    public Alerter enableInfiniteDuration(final boolean infiniteDuration) {
        if (getAlert() != null) {
            getAlert().setEnableInfiniteDuration(infiniteDuration);
        }
        return this;
    }


    /**
     * Sets the Alert Hidden Listener
     *
     * @param listener OnHideAlertListener of Alert
     * @return This Alerter
     */
    public Alerter setOnHideListener(final OnHideAlertListener listener) {
        if (getAlert() != null) {
            getAlert().setOnHideListener(listener);
        }
        return this;
    }


    /**
     * Enables swipe to dismiss
     *
     * @return This Alerter
     */
    public Alerter enableSwipeToDismiss() {
        if (getAlert() != null) {
            getAlert().enableSwipeToDismiss();
        }
        return this;
    }


    /**
     * Disable touch events outside of the Alert
     *
     * @return This Alerter
     */
    public Alerter disableOutsideTouch() {
        if (getAlert() != null) {
            getAlert().disableOutsideTouch();
        }

        return this;
    }

    /**
     * Enable or disable progress bar
     *
     * @param enable True to enable, False to disable
     * @return This Alerter
     */
    public Alerter enableProgress(final boolean enable) {
        if (getAlert() != null) {
            getAlert().setEnableProgress(enable);
        }

        return this;
    }


    /**
     * Set the Progress bar color from a color resource
     *
     * @param color The color resource
     * @return This Alerter
     */
    public Alerter setProgressColorInt(final int color) {
        if (getAlert() != null) {
            getAlert().setProgressColorInt(color);
        }

        return this;
    }

    public Alerter setOnShowListener(final OnShowAlertListener listener) {
        if (getAlert() != null) {
            getAlert().setOnShowListener(listener);
        }
        return this;
    }

    /**
     * Gets the Alert associated with the Alerter
     *
     * @return The current Alert
     */
    Alert getAlert() {
        return alert;
    }

    /**
     * Sets the Alert
     *
     * @param alert The Alert to be references and maintained
     */
    private void setAlert(final Alert alert) {
        this.alert = alert;
    }


    public Alerter setEnableIconAnim(boolean isEnableIconAnim) {
        if (getAlert() != null) {
            getAlert().setEnableIconAnim(isEnableIconAnim);
        }
        return this;
    }

    public Alerter setEnableCustomLeftIconAnim(boolean isEnableIconAnim) {
        if (getAlert() != null) {
            getAlert().setEnableCustomLeftIconAnim(isEnableIconAnim);
        }
        return this;
    }

    public Alerter setCustomLeftIconBig(int customLeftIconBig) {
        if (getAlert() != null) {
            getAlert().setCustomLeftIconBig(customLeftIconBig);
        }
        return this;
    }

    public Alerter setCustomLeftIconSmall(int customLeftIconSmall) {
        if (getAlert() != null) {
            getAlert().setCustomLeftIconSmall(customLeftIconSmall);
        }
        return this;
    }

    public Alerter setEnableRightIcon(boolean enable) {
        if (getAlert() != null) {
            getAlert().setEnableRightIcon(enable);
        }
        return this;
    }


    public Alerter setEnableOnlyRightIcon(boolean enable) {
        if (getAlert() != null) {
            getAlert().setEnableOnlyRightIcon(enable);
        }
        return this;
    }

    public Alerter setCustomRightIconBig(int customLeftIconBig) {
        if (getAlert() != null) {
            getAlert().setCustomRightIconBig(customLeftIconBig);
        }
        return this;
    }

    public Alerter setCustomRightIconSmall(int customLeftIconSmall) {
        if (getAlert() != null) {
            getAlert().setCustomRightIconSmall(customLeftIconSmall);
        }
        return this;
    }

    public Alerter setEnableCustomRightIconAnim(boolean isEnableIconAnim) {
        if (getAlert() != null) {
            getAlert().setEnableCustomRightIconAnim(isEnableIconAnim);
        }
        return this;
    }

    public Alerter setRightIconTop() {
        if (getAlert() != null) {
            getAlert().setRightIconTop();
        }
        return this;
    }

    public Alerter setSoundUri(Uri uri) {
        if (getAlert() != null) {
            getAlert().setSound(uri);
        }
        return this;
    }


    WeakReference<Component> getComponentWeakReference() {
        return componentWeakReference;
    }


    private void setActivity(final AbilitySlice activity, Component component) {
        activityWeakReference = new WeakReference<>(activity);
        componentWeakReference = new WeakReference<>(component);
    }
}